package com.teemor.blog.service.impl;


import com.alibaba.fastjson.JSON;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sun.org.apache.bcel.internal.generic.I2F;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.teemor.blog.bean.condition.TbArticleCondition;
import com.teemor.blog.bean.condition.TbArticleExtendCondition;
import com.teemor.blog.bean.dto.input.article.AddArticleIDTo;
import com.teemor.blog.bean.dto.output.articleextend.QryArticleExtendODTo;
import com.teemor.blog.bean.entity.TbArticle;
import com.teemor.blog.bean.entity.TbArticleExtend;
import com.teemor.blog.bean.dto.input.article.QryArticlesIDTo;
import com.teemor.blog.bean.dto.output.article.QryArchivesODTo;
import com.teemor.blog.bean.dto.output.article.QryArticleODTo;
import com.teemor.blog.bean.dto.output.article.QryArticlesODTo;
import com.teemor.blog.bean.entity.TbFootprint;
import com.teemor.blog.bean.entity.TbTopic;
import com.teemor.blog.bean.enums.ArticleStates;
import com.teemor.blog.mapper.TbArticleExtendMapper;
import com.teemor.blog.mapper.TbArticleMapper;
import com.teemor.blog.mapper.TbTopicMapper;
import com.teemor.blog.rpc.IArticleSearchRpc;
import com.teemor.blog.service.IArticleService;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import com.teemor.blog.service.IFootprintService;
import com.teemor.common.bean.base.PageBean;
import com.teemor.common.bean.datasource.input.QryArticlesIPo;
import com.teemor.common.bean.datasource.output.QryArticlesOPo;
import com.teemor.common.bean.model.EsOutputModel;
import com.teemor.common.bean.model.EsQueryModel;
import com.teemor.common.bean.utils.BeanConvertor;
import com.teemor.common.bean.utils.UUIDUtils;
import com.teemor.common.bean.utils.kafka.BaseKafkaProducer;
import com.teemor.common.bean.utils.enums.DataStatus;
import com.teemor.common.bean.utils.redis.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

/**
  * @author: zhoulk
  * @Description: 原子服务实现
  * @date: 2019/11/26 14:50:14
 */
@Service
@Slf4j
public class ArticleServiceImpl implements IArticleService {
    @Autowired
    private TbArticleMapper tbArticleMapper;
    @Autowired
    private IArticleSearchRpc iArticleSearchRpc;
    @Autowired
    private TbArticleExtendMapper extendMapper;
    @Autowired
    private TbTopicMapper tbTopicMapper;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private IFootprintService footprintService;

    @Override
    public int countArticle(TbArticleCondition condition) {
        return tbArticleMapper.countArticleByCondition(condition);
    }

    @Override
    public PageBean<QryArticlesODTo> qryArticles(TbArticleCondition condition) {
        condition.setDataState(DataStatus.USE.value());
        condition.setOrderByClause("tb_article.create_time desc");
        if (condition.getPage() != null) { //如果传入了分页条件则开启分页
            PageHelper.startPage(condition.getPage(), condition.getPageSize());
        }
        List<TbArticle> articles = tbArticleMapper.selectArticleByCondition(condition);
        if (CollectionUtils.isEmpty(articles)) { //查询为空时，直接返回空列表
            return PageBean.create(null, QryArticlesODTo.class);
        }

        //查询文章扩展信息
        List<Integer> atcIds = articles.stream().map(TbArticle::getAtcId).collect(Collectors.toList());
        List<QryArticlesODTo> articlesODTos = BeanConvertor.convertBeanList(articles, QryArticlesODTo.class);
        Map<Integer, QryArticlesODTo> map = articlesODTos.stream().collect(Collectors.toMap(QryArticlesODTo::getAtcId, v -> v));
        TbArticleExtendCondition articleExtend = new TbArticleExtendCondition();
        articleExtend.setAtcIds(atcIds);
        List<TbArticleExtend> tbArticleExtends = extendMapper.selectArticleExtendByCondition(articleExtend);
        List<QryArticleExtendODTo> articleExtendODTos = BeanConvertor.convertBeanList(tbArticleExtends, QryArticleExtendODTo.class);
        articleExtendODTos.forEach(v -> {
            if (map.containsKey(v.getAtcId()))
                map.get(v.getAtcId()).setArticleExtend(v);
        });

        //如果是分页则查询总数
        if (condition.getPage() != null) {
            Integer total = tbArticleMapper.countArticleByCondition(condition);
            return PageBean.create(articlesODTos, total, QryArticlesODTo.class);
        }

        return PageBean.create(articlesODTos, QryArticlesODTo.class);
    }

    @Override
    public QryArticleODTo qryArticleById(Integer atcId, Integer flag, String ip) {
        TbArticle article = tbArticleMapper.selectArticleByAtcId(atcId);
        QryArticleODTo articleODTo = BeanConvertor.convertBean(article, QryArticleODTo.class);
        if (Objects.nonNull(article)) {
            if (flag == 1) {
                ip = StringUtils.isBlank(ip) ? UUIDUtils.generateUuid() : ip;
                boolean access = RedisUtils.simpleLimit(getClass().getSimpleName() + "_" + ip + "_" + atcId, 60 * 60 , 1) > -1;
                TbArticleExtend articleExtend = extendMapper.selectArticleExtendByAtcId(atcId);
                if (articleExtend == null) {
                    articleExtend = new TbArticleExtend();
                    articleExtend.setAtcId(atcId);
                    articleExtend.setBrowseNum(1);
                    extendMapper.insertArticleExtend(articleExtend);
                } else {
                    if (access) {
                        articleExtend.setAtcId(atcId);
                        articleExtend.setBrowseNum(articleExtend.getBrowseNum() + 1);
                        extendMapper.updateArticleExtendByAtcId(articleExtend);
                    }
                }
                footprintService.addFootprint(new TbFootprint(atcId, ip));
                articleODTo.setArticleExtend(articleExtend);
            }
            TbTopic tbTopic = tbTopicMapper.selectTopicByTopicId(article.getTopicId());
            articleODTo.setTbTopic(tbTopic);
        }
        return articleODTo;
    }

    @Override
    public int addArticle(AddArticleIDTo inParam) {
        inParam.setCreateTime(new Date());
        inParam.setDataState(DataStatus.USE.value());
        inParam.setAtcState(ArticleStates.WAIT_PUBLISH.value());
        TbArticle article = BeanConvertor.convertBean(inParam, TbArticle.class);
        if (inParam.getCopy() == 1) {
            String result = restTemplate.getForObject("https://note.youdao.com/yws/public/note/" + inParam.getCopyId(), String.class);
            Map<String, Object> resultMap = JSON.parseObject(result).getInnerMap();
            String content = formatterContent(resultMap.get("content").toString());
            Document doc = Jsoup.parse(content);
            Element dirElement = doc.getElementsByAttributeValue("yne-bulb-type", "catalogue-wrap").first();
            if (dirElement != null) {
                Elements elements = dirElement.getElementsByTag("div");
                for (Element div : elements) {
                    div.removeAttr("style");
                }
                Elements blockquotes = dirElement.getElementsByTag("blockquote");
                for (Element element : blockquotes) {
                    element.attr("style", "margin:0 0 0 20px;border:none;padding:0px;");
                }
                Elements aelements = dirElement.getElementsByTag("a");
                for (Element element : aelements) {
                    element.attr("style", "text-overflow: ellipsis;overflow: hidden;white-space: nowrap;display: block;");
                }
                String dir = dirElement.toString();
                article.setDir(dir);
                dirElement.remove();
            }
//            content = doc.toString();
//            content.replaceAll(" <","<");
//            content.replaceAll("> ",">");
//            content.replaceAll("\n" +
//                    " {4}","");
            article.setContent(content);
        }
        return tbArticleMapper.insertArticle(article);
    }


    private static String formatterContent(String content) {

        String temp = content;

        temp = temp.replaceAll("\\\\ \"", "'").replaceAll("\\\\\"", "'");

        temp = temp.replaceAll("\\\\/", "/");
        temp = temp.replaceAll("\\\\n", "<br />");
        temp = temp.replaceAll("src=\"http", "src=\"https");
        StringBuilder sb = new StringBuilder(temp);

        int index = 0;
        while ((index = sb.indexOf("yne-bulb-block=\"code\"", index + 1)) > 0) {
            int index2 = sb.indexOf("</div>", index + 1);
            sb.replace(index2, index2 + 6, "</code></pre>");
        }
        temp = sb.toString().replaceAll("<div yne-bulb-block=\"code\".*?>", "<pre><code>");
        content = temp;

        return content;
    }

    @Override
    public int updArticleById(TbArticle inParam) {
        return tbArticleMapper.updateArticleByAtcId(inParam);
    }

    @Override
    public int delArticleById(Integer atcId) {
        TbArticle article = new TbArticle();
        article.setDataState(DataStatus.DELETE.value());
        article.setAtcId(atcId);
        article.setDropTime(new Date());
        return tbArticleMapper.updateArticleByAtcId(article);
    }

    @Override
    public Map<String, Object> searchArticles(QryArticlesIDTo inParam, String scrollId) {
        QryArticlesIPo qryArticlesIPo = BeanConvertor.convertBean(inParam, QryArticlesIPo.class);
        qryArticlesIPo.setDataState(0);
        EsQueryModel<QryArticlesIPo> queryModel = new EsQueryModel<>();
        queryModel.setFilters(qryArticlesIPo);
        queryModel.setQueryValue(inParam.getQuery());
        queryModel.setQueryFields(new String[]{"title", "summary"});
        queryModel.setSize(10);
        queryModel.setScrollId(scrollId);
        EsOutputModel<QryArticlesOPo> outputModel = iArticleSearchRpc.searchArticles(queryModel);
        List<QryArticlesOPo> qryArticlesOPos = outputModel.getData();
        scrollId = outputModel.getScrollId();
        List<QryArticlesODTo> articlesODTos = BeanConvertor.convertBeanList(qryArticlesOPos, QryArticlesODTo.class);
        Map<String, Object> map = new HashMap<>();
        map.put("articles", articlesODTos);
        map.put("scrollId", scrollId);
        return map;
    }

    @Override
    public List<QryArchivesODTo> archive() {
        return tbArticleMapper.archive();
    }

    @Override
    public Map<String, Object> updArticleState(Integer atcId, Integer atcState) {
        TbArticle article = new TbArticle();
        article.setAtcId(atcId);
        article.setAtcState(atcState);
        int num = tbArticleMapper.updateArticleByAtcId(article);
        Map<String, Object> map = new HashMap<>();
        map.put("flag", num > 0);
        return map;
    }

}